module BoxBuilder
	
	# The box builder class is used from the "box" method.
	# When the text method is called, it sets it so that
	# fields? will return true.  box is setup so that it won't
	# display at all if no fields have value
	class BoxBuilderClass
		def initialize(model)
			@model = model
		end
		
		# <%= f.box_row_text('FieldName', 'Value') %>
		def box_row_text(name, value)
			if !value || value == '' || value == nil
				# Value is not set, so we can get rid of this
				return ''
			end
				
			html = []
			html << '<div class="field clearfix"><div class="left">' << name << '</div><div class="right">' << value << '</div></div>'
			
			@fields = true
			return html.join('')
		end
		
		# <%= f.box_fields([:field1, :field2]) %>
		def box_fields(fields)
			return '' if @model == nil
			
			html = ''

			fields.each do |field_name|
				html += box_field(field_name)
			end

			return html
		end
				
		# BoxBuilder::box_field is used to render the text version of a field
		def box_field(field_name)
			fields = @model.class.field_data
			field = fields[field_name.to_sym]

			return box_row_text(field[:label], @model.send(field_name.to_sym))
		end
		
		
		def fields?()
			return @fields || false
		end
	end
	
	
	# The BoxBuilder class is used from the box method.
	# Boxes are intended for displaying fields from model objects, however
	# other content can be added in as well by passing in a block (see second example)
	#
	# If the fields contained in a block do not have any content (are nil or == '')
	# then the box will not be displayed at all (this is the feature)
	#
	# A box can be created in the following ways:
	#
	#  <%= box('Details', :model => @member, :fields => [:email, :about_me, :things_i_like]) %>
	#
	# This first way will display the :fields from the @member model using the 
	# box_row_text method (which generates something like this)
	#  <div class="box">
	#    <h2>Details</h2>
	#    <div class="field">
	#      <div class="left">Field Label</div>
	#      <div class="right">Field Value</div>
	#    </div>
	#    ...
	#  </div>
	#
	# The second way lets you pass in a block, and specify fields using the box_row method
	# on the form helper
	#
	#  <% box('Details', :model => @member) do |f| %>
	#    <%= f.box_row([:email, :name]) %>
	#  <% end %>
	
	def box(title, options={}, &block)
		bf = BoxBuilderClass.new(options[:model] || nil)

		if block_given?
			inner = capture(bf, &block)
		elsif options[:model] && options[:fields]
			inner = []

			field_data = options[:model].class.field_data

			options[:fields].each do |field|
				fld_data = field_data[field.to_sym]
				next if !fld_data
				
				label = fld_data[:label]
				
				row_html = options[:model].send(field.to_sym)
				
				# Don't run h on the value if the model specified the :html attribute to true
				if fld_data[:html] == true
					row_value = row_html					
				else
					row_value = h(row_html).gsub(/\n/, '<br />')
				end
				inner << bf.box_row_text(label, row_value)
			end
			inner = inner.join('')
		end

		html = '<div class="box">'
		html << '<h2>' + h(title) + '</h2>' if title != nil && title != ''
		html << inner + '</div>'
		if bf.fields? || (options[:force] && options[:force] == true)
			if block_given?
				concat(html, block.binding)
			else
				return html
			end
		else
			return ''
		end
		
	end
	
	
end
